package service

import (
	"errors"
	"fmt"
	"goscan-mgt/model"
	"goscan-mgt/repository"
	"goscan-mgt/utils"
	"log"
	"strings"
)

// ProjectService 结构体定义了与项目相关的业务逻辑
type ProjectService struct {
	repo *repository.ProjectRepository // 项目仓库
}

// NewProjectService 创建一个新的ProjectService实例
func NewProjectService() *ProjectService {
	repo := repository.NewProjectRepository() // 获取项目仓库实例
	return &ProjectService{repo: repo}
}

// CreateProject 创建一个新的项目
func (s *ProjectService) CreateProject(project *model.Project) error {
	project.ProjectName = strings.TrimSpace(project.ProjectName)
	if project.ProjectName == "" {
		return errors.New("项目名称不能为空")
	}

	return s.repo.Create(project)
}

func (s *ProjectService) StartScan(cidr string) (*model.Project, error) {
	cidr = strings.TrimSpace(cidr)
	if cidr == "" {
		return nil, errors.New("IP地址或网段不能为空")
	}
	// 检查CIDR格式是否正确
	if !utils.IsValidCIDR(cidr) {
		return nil, errors.New("无效的IP地址或网段格式")
	}
	projectName := s.generateProjectNameByCidr(cidr, nil)
	project := &model.Project{
		ProjectName: projectName,
	}
	//检查项目名称是否存在
	existingProjects, err := s.repo.FindByName(project.ProjectName + "%")
	if err != nil {
		return nil, fmt.Errorf("查询项目失败: %w", err)
	}
	project.ProjectName = s.generateProjectNameByCidr(cidr, existingProjects)
	err = s.repo.Create(project)
	if err == nil {
		err = s.repo.UpdateStatusToOneExceptID(project.ID)
		// 启动异步扫描任务
		NewScanAsyncTask(cidr, project.ID).Start()
	}
	return project, err
}

// GetProjectByID 根据ID获取项目
func (s *ProjectService) GetProjectByID(id uint) (*model.Project, error) {
	return s.repo.GetByID(id)
}

// UpdateProject 更新项目
func (s *ProjectService) UpdateProject(project *model.Project) error {
	if project.ID == 0 {
		return errors.New("项目ID不能为空")
	}
	log.Println("project:", project)
	return s.repo.Update(project)
}

// DeleteProject 删除项目
func (s *ProjectService) DeleteProject(id uint) error {
	return s.repo.Delete(id)
}

// GetAllProjects 获取所有项目
func (s *ProjectService) GetAllProjects() ([]model.Project, error) {
	return s.repo.GetAll()
}

// GetPaginatedProjects 获取分页项目列表
func (s *ProjectService) GetPaginatedProjects(page, pageSize int) (*utils.Pagination[model.Project], error) {
	return s.repo.GetPaginated(page, pageSize)
}

// UpdateProjectStatus 更新项目状态
func (s *ProjectService) UpdateProjectStatus(id uint, status, scanCount int) error {
	project, err := s.GetProjectByID(id)
	if err != nil {
		return err
	}

	project.Status = status
	if scanCount != 0 {
		project.ScanCount = scanCount
	}
	return s.repo.Update(project)
}

// 根据cidr生成项目名称
func (s *ProjectService) generateProjectNameByCidr(cidr string, projects []model.Project) string {
	projectName := fmt.Sprintf("%s 扫描", cidr)
	if projects == nil {
		return projectName
	}
	//项目名称命名规则 ：cidr + 扫描 或 cidr + 扫描(index),如果存在【cidr + 扫描 】则取【cidr + 扫描(index)】的形式,如果【cidr + 扫描(index)】存在，则取【cidr + 扫描(index+1)】的形式
	exists := false
	maxIndex := 0
	for _, p := range projects {
		if p.ProjectName == projectName {
			exists = true
		} else if strings.HasPrefix(p.ProjectName, fmt.Sprintf("%s 扫描(", cidr)) && strings.HasSuffix(p.ProjectName, ")") {
			// 提取括号内的数字
			name := p.ProjectName
			start := strings.LastIndex(name, "(")
			end := strings.LastIndex(name, ")")
			if start != -1 && end != -1 && end > start+1 {
				var idx int
				_, err := fmt.Sscanf(name[start+1:end], "%d", &idx)
				if err == nil && idx > maxIndex {
					maxIndex = idx
				}
			}
		}
	}
	if exists {
		projectName = fmt.Sprintf("%s 扫描(%d)", cidr, maxIndex+1)
	}
	return projectName
}
